<?php
namespace app\common\utils;
use fast\Random;
use Jenssegers\Agent\Agent;
use think\exception\HttpResponseException;
use think\Model;
use think\Request;
use think\Response;

/**
 * 公用方法服务
*/

class Utils {
    /**
     * 操作成功返回的数据
     * @param string $msg   提示信息
     * @param mixed $data   要返回的数据
     * @param int   $code   错误码，默认为1
     * @param string $type  输出类型
     * @param array $header 发送的 Header 信息
     */
    public static function success($msg = '', $data = null, $code = 1, $type = null, array $header = [])
    {
        self::result($msg, $data, $code, $type, $header);
    }

    /**
     * 操作失败返回的数据
     * @param string $msg   提示信息
     * @param mixed $data   要返回的数据
     * @param int   $code   错误码，默认为0
     * @param string $type  输出类型
     * @param array $header 发送的 Header 信息
     */
    public static function error($msg = '', $data = null, $code = 0, $type = null, array $header = [])
    {
        self::result($msg, $data, $code, $type, $header);
    }
    /**
     * 返回封装后的 API 数据到客户端
     * @access protected
     * @param mixed  $msg    提示信息
     * @param mixed  $data   要返回的数据
     * @param int    $code   错误码，默认为0
     * @param string $type   输出类型，支持json/xml/jsonp
     * @param array  $header 发送的 Header 信息
     * @return void
     * @throws HttpResponseException
     */
    public static function result($msg, $data = null, $code = 0, $type = null, array $header = [])
    {
        if (!$data && $data !== '') {
            $data = [];
        }
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'time' => Request::instance()->server('REQUEST_TIME'),
            'data' => $data,
        ];
        // 如果未设置类型则自动判断
        $type = $type ? $type : (input(config('var_jsonp_handler')) ? 'jsonp' : 'json');

        if (isset($header['statuscode']))
        {
            $code = $header['statuscode'];
            unset($header['statuscode']);
        }
        else
        {
            //未设置状态码,根据code值判断
            $code = $code >= 1000 || $code < 200 ? 200 : $code;
        }
        $response = Response::create($result, $type, $code)->header($header);
        throw new HttpResponseException($response);
    }
    /**
     * 字符串替换
     */
    public static function sr($str = '', $target = '', $content = ''){

        return str_replace($target, $content, $str);
    }

    /**
     * 时间戳格式化
     * @param int $time
     * @return string 格式化后的时间字符串
     */
    public static function time_format($time = NULL,$style='Y-m-d H:i:s'){
        if (empty($time) || $time == 0) {
            return '';
        }
        $time = $time === NULL ? '' : intval($time);
        return date($style, $time);
    }



    /**
     * 处理字符串
     */
    public static function explodeStr($str, $s = ',') {
        if ($str === '') {
            $arr = [];
        } else {
            $arr = explode($s, $str);
        }

        return $arr;
    }

    /**
     * 处理数组
     */
    public static function implodeArr($arr, $s = ',') {
        if (empty($arr)) {
            $str = '';
        } else {
            $str = implode($s, $arr);
        }

        return $str;
    }

    /**
     * 专门用来处理两个字符串 去除相同的部分 $str1返回
     */
    public static function deleteStrSame($str1, $str2) {
        $arr1 = self::explodeStr($str1);
        $arr2 = self::explodeStr($str2);
        $realArr = array_diff($arr1, $arr2);
        $realStr = self::implodeArr($realArr);

        return $realStr;
    }

    /**
     * 专门用来处理两个字符串 合并两个字符串
     */
    public static function combinStr($str1, $str2) {
        $arr1 = self::explodeStr($str1);
        $arr2 = self::explodeStr($str2);
        $realArr = array_flip($arr1) + array_flip($arr2);
        $realArr = array_keys($realArr);

        $realStr = self::implodeArr($realArr);

        return $realStr;
    }

    /*
     * 计算数组中元素的和
     * */
    public static function getArrHz($arr) {
        $hz = 0;
        foreach ($arr as $k => $v) {
            $hz += $v;
        }

        return $hz;
    }

    /*
     浮点数计算函数 取2位小数 后面舍去
     $user_money 用户余额
     $money 要处理的钱数
     $conn 连接符号
 */
    public static function processMoney($user_money, $money, $conn, $bcscale = 2) {
        $user_money = (string)$user_money;
        $money = (string)$money;
        $balance = '';
        bcscale($bcscale);
        switch ($conn) {
            case '-': $balance = bcsub($user_money, $money); return $balance; break;
            case '+': $balance = bcadd($user_money, $money); return $balance; break;
            case '*': $balance = bcmul($user_money, $money); return $balance; break;
            case '/': $balance = bcdiv($user_money, $money); return $balance; break;

            default: return ''; break;
        }
    }

    /** 从一个数组种随机几个元素*/
    public static function rankArray($arr = [], $num = 1) {
        if (empty($arr)) {
            return V(0, '数组成员不能为空');
        }
        if (count($arr) < $num) {
            return V(0, '数组元素数量小于要随机的数量');
        }

        $temp = [];
        for ($i = 1; $i <= $num; $i++) {
            array_push($temp, $arr[array_rand($arr, 1)]);
        }

        return $temp;
    }

    /**
        解析数组 主要是配置专用
     * @$value 为解析的字符串
     */
    public static function parse($value){
        $array = preg_split('/[,;\r\n]+/', trim($value, ",;\r\n"));

        if(strpos($value,':')){
            $value  = array();
            foreach ($array as $val) {
                list($k, $v) = explode(':', $val);
                $value[$k]   = $v;
            }
        }else{
            $value =    $array;
        }

        return $value;
    }

    /*
    * 彩票用来获取 开奖结果的
    * */
    public static function doCurl($url) {
        // 执行并获取内容
        $url = trim($url);
        $ch = curl_init(); // 初始化
        // 设置选项
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);

        if(stripos($url,'https') === 0){
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        }

        $output  = curl_exec($ch);

        // 释放句柄
        curl_close($ch);
        return json_decode($output, true);
    }


    /**
     * 获取时间戳
     * $Ymd = Y 年
     * $Ymd = m 月
     * $Ymd = d 日
     * $Ymd = NULL 当前时间戳
     * $xia = true 是否取下次开始时间戳：取下年开始时间戳 或者下月开始时间戳  或者明日开始时间戳
     */
    public static function  getTime($Ymd=NULL,$xia=false){
        if($Ymd=='Y' && $xia==true){
            //取下个年度开始时间戳
            return strtotime((date('Y',time())+1).'-01-01 00:00:00');
        }
        else if($Ymd=='Y'){
            //取本年度开始时间戳
            return strtotime(date('Y',time()).'-01-01 00:00:00');
        }
        else if($Ymd=='m' && $xia==true){
            //取下个月度开始时间戳
            $xiayue_nianfen    =    date('Y',time());
            $xiayue_yuefen    =    date('m',time());
            if($xiayue_yuefen==12){
                $xiayue_nianfen    +=    1;    //如果月份等于12月，那么下月年份+1
                $xiayue_yuefen    =    1;    //如果月份等于12月，那么下月月份=1月
            }
            else{
                $xiayue_yuefen    +=    1;    //如果月份不是12月，那么在当前月份上+1
            }
            return strtotime($xiayue_nianfen.'-'.$xiayue_yuefen.'-01 00:00:00');
        }
        else if($Ymd=='m'){
            //取本月度开始时间戳
            return strtotime(date('Y-m',time()).'-01 00:00:00');
        }
        else if($Ymd=='d' && $xia==true){
            //取明日开始时间戳
            return strtotime(date('Y-m-d',time()).' 00:00:00')+86400;
        }
        else if($Ymd=='d'){
            //取今日开始时间戳
            return strtotime(date('Y-m-d',time()).' 00:00:00');
        }
        else{
            //取当前时间戳
            return time();
        }
    }


    /**
     * 获取指定年月日的开始时间戳和结束时间戳(本地时间戳非GMT时间戳)
     * [1] 指定年：获取指定年份第一天第一秒的时间戳和下一年第一天第一秒的时间戳
     * [2] 指定年月：获取指定年月第一天第一秒的时间戳和下一月第一天第一秒时间戳
     * [3] 指定年月日：获取指定年月日第一天第一秒的时间戳
     * @param  integer $year     [年份]
     * @param  integer $month    [月份]
     * @param  integer $day      [日期]
     * @return array('start' => '', 'end' => '')
     */
    public static function getStartAndEndUnixTimestamp($year = 0, $month = 0, $day = 0)
    {
        if(empty($year))
        {
            $year = date("Y");
        }

        $start_year = $year;
        $start_year_formated = str_pad(intval($start_year), 4, "0", STR_PAD_RIGHT);
        $end_year = $start_year + 1;
        $end_year_formated = str_pad(intval($end_year), 4, "0", STR_PAD_RIGHT);

        if(empty($month))
        {
            //只设置了年份
            $start_month_formated = '01';
            $end_month_formated = '01';
            $start_day_formated = '01';
            $end_day_formated = '01';
        }
        else
        {

            $month > 12 || $month < 1 ? $month = 1 : $month = $month;
            $start_month = $month;
            $start_month_formated = sprintf("%02d", intval($start_month));

            if(empty($day))
            {
                //只设置了年份和月份
                $end_month = $start_month + 1;

                if($end_month > 12)
                {
                    $end_month = 1;
                }
                else
                {
                    $end_year_formated = $start_year_formated;
                }
                $end_month_formated = sprintf("%02d", intval($end_month));
                $start_day_formated = '01';
                $end_day_formated = '01';
            }
            else
            {
                //设置了年份月份和日期
                $startTimestamp = strtotime($start_year_formated.'-'.$start_month_formated.'-'.sprintf("%02d", intval($day))." 00:00:00");
                $endTimestamp = $startTimestamp + 24 * 3600 - 1;
                return array('start' => $startTimestamp, 'end' => $endTimestamp);
            }
        }

        $startTimestamp = strtotime($start_year_formated.'-'.$start_month_formated.'-'.$start_day_formated." 00:00:00");
        $endTimestamp = strtotime($end_year_formated.'-'.$end_month_formated.'-'.$end_day_formated." 00:00:00") - 1;
        return array('start' => $startTimestamp, 'end' => $endTimestamp);
    }

    /**
     * 递归创建目录
     */
    public static function directory( $dir ){
        return  is_dir ( $dir ) or self::directory(dirname( $dir )) and  @mkdir ( $dir , 0777);
    }

    /**统计专用*/
    public static function getLengthAndFormat($time) {
        $days = ceil($time/(3600*24));
        $data = [];
        if ($days <= 1) {
            $data['date_type'] = 'hours';
            $data['style'] = 'H:00:00';
            $data['length'] = 24;
        } else if ($days <= 30) {
            $data['date_type'] = 'days';
            $data['style'] = 'Y-m-d';
            $data['length'] = $days;
        } else if ($days <= 365) {
            $data['date_type'] = 'months';
            $data['style'] = "Y-m";
            $data['length'] = ceil($days/30);
        } else {
            $data['date_type'] = 'years';
            $data['style'] = "Y";
            $data['length'] = ceil($days/365);
        }

        return $data;
    }

    /**
     * 判断文件是否存在，支持本地及远程文件
     * @param  String  $file 文件路径
     * @return Boolean
     */
    public static function check_file_exists($file){
        // 远程文件
        if(strtolower(substr($file, 0, 4))=='http'){

            $header = get_headers($file, true);

            return isset($header[0]) && (strpos($header[0], '200') || strpos($header[0], '304'));

            // 本地文件
        }else{
            //上层目录必须有权限
            return file_exists($file);
        }

    }

    /**
     * 文件字节大小显示成M,G和K
     * @param size
     * @return
     */
    public static function displayFileSize($size) {
        $kb = 1024;
        $mb = $kb * 1024;
        $gb = $mb * 1024;
        if ($size >= $gb) {
            return sprintf("%.1f GB",  $size / $gb);
        } else if ($size >= $mb) {
             $value = $size / $mb;
             return sprintf($value > 100 ? "%.0f MB" : "%.1f MB", $value);
        } else if ($size >= $kb) {
            $value = $size / $kb;
            return sprintf($value > 100 ? "%.0f KB" : "%.1f KB", $value);
        } else {
            return sprintf("%d B", $size);
        }



    }

    /**
     * 判断是否为微信客户端
     */
    public static function isWx() {
        $agent = new Agent();
        $borwer = $agent->getUserAgent();
        $res = strpos($borwer, 'MicroMessenger');

        if ($res !== false) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * [将Base64图片转换为本地图片并保存]
     * @param $base64_image_content [要保存的Base64]
     * @param $path [要保存的路径]
     * @return bool|string
     */
    public static function base64_image_content($base64_image_content, $name = ''){
        //匹配出图片的格式
        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){
            $type = $result[2];
            $returnUrl = "/uploads/".date('Ymd',time())."/";
            $basePutUrl = ROOT_PATH . '/public' . $returnUrl;

            if(!file_exists($basePutUrl)){
                //检查是否有该文件夹，如果没有就创建，并给予最高权限
                mkdir($basePutUrl, 0700);
            }

            if ($name == '') {
                $name = Random::uuid() . ".{$type}";
            }
            $local_file_uzl = $basePutUrl.$name;

            if (file_put_contents($local_file_uzl, base64_decode(str_replace($result[1], '', $base64_image_content)))){
                //TODO 个人业务的FTP 账号图片上传
                return $returnUrl . $name;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }


    public static function get_last_time($time = NULL) {
        $text = '';
        $time = $time === NULL || $time > time() ? time() : intval($time);
        $t = time() - $time; //时间差 （秒）
        $y = date('Y', $time)-date('Y', time());//是否跨年
        switch($t){
            case $t == 0:
                $text = '刚刚';
                break;
            case $t < 60:
                $text = $t . '秒前'; // 一分钟内
                break;
            case $t < 60 * 60:
                $text = floor($t / 60) . '分钟前'; //一小时内
                break;
            case $t < 60 * 60 * 24:
                $text = floor($t / (60 * 60)) . '小时前'; // 一天内
                break;
            case $t < 60 * 60 * 24 * 3:
                $text = floor($time/(60*60*24)) ==1 ?'昨天 ' . date('H:i', $time) : '前天 ' . date('H:i', $time) ; //昨天和前天
                break;
            case $t < 60 * 60 * 24 * 30:
                $text = date('m月d日 H:i', $time); //一个月内
                break;
            case $t < 60 * 60 * 24 * 365&&$y==0:
                $text = date('m月d日', $time); //一年内
                break;
            default:
                $text = date('Y年m月d日', $time); //一年以前
                break;
        }

        return $text;
    }



}
